/**
 *    Copyright 2009 Seth Albnaese
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 
package org.aquiferserver.client.flex 
{
	import flash.utils.ByteArray;
	import org.aquiferserver.client.flex.logging.Log;
	import org.aquiferserver.client.flex.logging.LogFactory;
	
	/**
	 * ...
	 * @author Seth Albanese
	 * @version $Id: AquiferMessage.as 30 2009-05-11 17:03:45Z salbanese0080@gmail.com $
	 */
	public class AquiferMessage 
	{
		
		public static var MT_PEER:String = "!_PEER";
		public static var MT_SERV:String = "!_SERV";
		public static var MT_HANDSHAKE:String = "!_HSM";
		public static var MT_CONNECTED:String = "!_GO";
		
		public static var CMD_DISCONNECT:String = "!_BYE";
		
		protected static var logger:Log = LogFactory.getLog( "org.aquiferserver.client.flex.AquiferMessage" );
		
		public var message:Object;
		public var from:int;
		public var data:Object;
		
		public var type:String = MT_PEER;
		
		public function AquiferMessage( serverMessage:String ) 
		{
			var vars:Array = serverMessage.split( "|" );
			
			type = vars.shift();
			
			switch ( type )
			{
				case( MT_HANDSHAKE ):					
					parseHandshakeMessage( vars );
				break;
				
				case( MT_SERV ):					
					parseServerMessage( vars );
				break;
				
				case( MT_PEER ):
					parsePeerMessage( vars );
				break;
				
				case( MT_CONNECTED ):
					type = MT_CONNECTED;
				break;
				
				default:
					throw new Error( "Unrecognized message type for [ " + serverMessage + " ]" );
				break;
			}			
		}
		
		private function parsePeerMessage( vars:Array ) : void 
		{
			for ( var i:int = 0; i < vars.length; i++ )
			{
				var pair:Array = vars[ i ].split( ":" );
				
				if ( pair.length != 3 )
				{
					throw new Error( "Malformed server message, unable to parse server object [ " + vars[ i ] + " ]" );
					continue;
				}
				
				var name:String = pair[ 0 ];
				var type:String = pair[ 1 ];
				var value:Object = pair[ 2 ];				
				
				switch ( name )
				{
					case 'from':
						if ( type != 'int' )
						{
							throw new Error( "Server type error." );
						} 
						from = int( value );
					break;
					case 'msg':
						if ( type != 'str' )
						{
							throw new Error( "Server type error." );
						} 
						message = SerializationCodec.deserialize( String( value ) );
					break;
					default:
						data[name] = {type:type, value:value};
					break;
				}
			}
		}
		
		private function parseHandshakeMessage( vars:Array ) : void 
		{
			data = new Object();
			from = -1;
			
			for ( var i:int = 0; i < vars.length; i++ )
			{
				var pair:Array = vars[ i ].split( ":" );
				
				switch ( pair[ 0 ] )
				{
					case 'cid':
						data.clientId = parseInt( pair[ 2 ] );
					break;
					
					case 'peers':						
						data.peers = pair[ 2 ].split( ',' );
					break;
					
					default:
						throw new Error( "Unexpected section of handshake message [ " + vars[ i ] + " ]" );
					break;
				}
			}
		}
		
		private function parseServerMessage( vars:Array ) : void 
		{
			data = new Object();
			from = -1;
			
			for ( var i:int = 0; i < vars.length; i++ ) 
			{
				var pair:Array = vars[ i ].split( ":" );
				if ( pair.length != 3 )
				{
					throw new Error( "Malformed server message, unable to parse server object [ " + vars[ i ] + " ]" );
					continue;
				}
				
				var name:String = pair.shift();
				var type:String = pair.shift();
				var value:String = pair.shift();
				
				switch( type )
				{
					case 'int':
						data[ name ] = parseInt( value );
					break;
					
					case 'a':
						data[ name ] = value.split( "," );
					break;
					
					case 'f':
						data[ name ] = parseFloat( value );
					break;
					
					default:
						data[ name ] = value;
					break;
				}
				
			}
		}
		
	}
	
}